#include <stdio.h>
#include <assert.h>

#include "SDL.h"
#include "SDL_ttf.h"
#include "SDL_mixer.h"
#include <ctime>
#include <vector>
#include <list>
#include <sstream>

using namespace std;

#include "GameBase.h"


int Gameon = 1; // a variable for handling game modes, menus, etc

typedef list<GameBase*> GameBaseList;

SDL_Surface* world = NULL; 

Mix_Music *Music = NULL;
Mix_Chunk *Flap = NULL;
Mix_Chunk *Blam = NULL;

SDL_Event event; // datastructure for event handling



int main( int argc, char* args[] )
{
    SDL_Init( SDL_INIT_EVERYTHING );   //Start SDL
	SDL_GrabMode SDL_WM_GrabInput(SDL_GRAB_ON); // grabs all keyboard and mouse use
	SDL_ShowCursor(0);

	if(Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2,4096)== -1)
	{
		assert(false);
	}

	TTF_Init();
	// SDL_OPENGL,  SDL_OPENGLBLIT, 
	world = SDL_SetVideoMode( 1280, 720, 16, SDL_SWSURFACE | SDL_FULLSCREEN); //setup backround, ( width, height, 32bit, what surface? )   

	//------------------------------------------
	//  variables for main gameplay mode
	int Background_X = 0;
	int Background_Y = 0;
	int BackgroundVelocity_X = 0;
	int BackgroundVelocity_Y = 0;
	int Mouse_x = 0, Mouse_y = 0;
	char Fire = 0; 
	unsigned int start,end; 
	int stats_ducks = 0;
	int stats_ducks_hit = 0;
	int DuckMake;

	// seed random # generator
	srand((unsigned int)(time(NULL)));

	// start with random # ducks
	DuckMake = (rand()%10);

	// declare world
	GameBaseList World;
	
	//set sound
	Music = Mix_LoadMUS(RESOURCEPATH"DuckRiff22050.wav");
	if(Music == NULL)
	{
		assert(false);
	}

	Blam = Mix_LoadWAV(RESOURCEPATH"GUNSHOT.WAV");
	if (Blam == NULL)
	{
		assert(false);
	}
	// load save game
	World.push_back(new BitmapObjectStatic(0,0,RESOURCEPATH"Background.bmp"));
	// background needs to be first
	// New object \/ below

	for (int i = 0 ; i < DuckMake; i++)
	{
		World.push_back(new BitmapAnimatedObject( (rand()%1300),(rand()%800), "duck", 4, 100, true, (rand()%10),(rand()%10)* ( (rand()%2) == 0 ? -1 : 1), true ) );
		stats_ducks++;
	}

	// New objects /\ above
	// Crosshair needs to be last
	World.push_back(new BitmapObject(200,200,RESOURCEPATH"crosshair.bmp"));

	TextObjectStatic Score(5,5,RESOURCEPATH"SLICKER.TTF" , 40 );

	char ScoreString[512] = "";
	//------------------------------------------
	
	unsigned long frameCount = 1;
	unsigned long framesPerSecond = 1;

	if(Mix_PlayMusic(Music, -1) == -1)
	{
		assert(false);
	}
	while(Gameon == 1)// Main gameplay mode
	{
		start = SDL_GetTicks();

		/*
		if (framesPerSecond > 60)
		{
			SDL_Delay( (framesPerSecond-60) * (1000/60) );
		}
		*/

		GameBase::Event EventToPass = GameBase::None;	

		// eat all the events before painting
		while (SDL_PollEvent(&event))
		{
			switch (event.type)
			{	
				case SDL_KEYDOWN:
					switch (event.key.keysym.sym)
					{
				// some legacy keyboard controll, 
						case SDLK_LEFT:
							BackgroundVelocity_X += -1;
							// constrain
							BackgroundVelocity_X = BackgroundVelocity_X < -20 ? -20 : BackgroundVelocity_X;
						break;

						case SDLK_RIGHT:
							BackgroundVelocity_X += 1;
							// constrain
							BackgroundVelocity_X = BackgroundVelocity_X > 20 ? 20 : BackgroundVelocity_X;
						break; 

						case SDLK_UP:
							BackgroundVelocity_Y += -1;
							// constrain
							BackgroundVelocity_Y = BackgroundVelocity_Y < -20 ? -20 : BackgroundVelocity_Y;
						break;

						case SDLK_DOWN:
							BackgroundVelocity_Y += 1;
							// constrain
							BackgroundVelocity_Y = BackgroundVelocity_Y > 20 ? 20 : BackgroundVelocity_Y;
						break; 

						case SDLK_SPACE:
							Fire = 1;
						break;
						
						case SDLK_ESCAPE:
							SDL_Quit();
							return 0;  
						break;
									
						case SDLK_d:
							 DuckMake = 1;
						break;

						case SDLK_f:
							 DuckMake = 25;
						break;


					}
					break;

				 case SDL_KEYUP:
					switch (event.key.keysym.sym)
					{
						case SDLK_LEFT:
							BackgroundVelocity_X = 0;
						break;

						case SDLK_RIGHT:
							BackgroundVelocity_X = 0;
						break;

						case SDLK_UP:
							BackgroundVelocity_Y = 0;
						break;

						case SDLK_DOWN:
							BackgroundVelocity_Y = 0;
						break; 
					}
					break;
					
				
				 case SDL_MOUSEMOTION:
						{
							Mouse_x = event.motion.x;
							Mouse_y = event.motion.y;

							BackgroundVelocity_X = Mouse_x;
							BackgroundVelocity_Y = Mouse_y;
						}
				 break; 
				 
				 case SDL_MOUSEBUTTONDOWN:
					 

				 break;

				 case SDL_MOUSEBUTTONUP:
					EventToPass = GameBase::Fire;

					if(Mix_PlayChannel(-1, Blam, 0) == -1)
					{
					}
				 break;
	

			}	 
		}// end event whileloop

		// handle reticle which is always last item
		int x;
		int y;

		World.back()->Move(BackgroundVelocity_X,BackgroundVelocity_Y);
		World.back()->GetPosition(x,y);

		// insert ducks 1 past background
		GameBaseList::iterator newDuckIter = World.begin();
		newDuckIter++;

		for (int i = 0 ; i < DuckMake; i++)
		{
			newDuckIter = World.insert(newDuckIter,new BitmapAnimatedObject( (rand()%1300),(rand()%800), "duck", 4, 100, true, (rand()%10),(rand()%10)* ( (rand()%2) == 0 ? -1 : 1) , true ));
			stats_ducks++;
		}
		DuckMake = 0;
		
		// paint entire world
		GameBaseList::iterator iter = World.begin();
		while(iter != World.end() )
		{
			if((*iter)->GetActive())
			{
				GameBase* pNewObject = (*iter)->Action(EventToPass,x,y);
				if (pNewObject != 0)
				{
					delete *iter;
					*iter = pNewObject;
				}
				(*iter)->Draw(world);

				// next object
				iter++;
			}
			else
			{
				stats_ducks_hit++;
				iter = World.erase(iter);	
			}
		}
		
		// update string  
		if (frameCount % 10 == 0)
		{
			sprintf(ScoreString,"%i of %i Ducks %i frame/sec",stats_ducks_hit,stats_ducks,1000/framesPerSecond);
		}
		Score.SetText(world, ScoreString, 255, 0, 0);
				
		SDL_Flip(world); //updates screen,
		end = SDL_GetTicks(); 
		
		framesPerSecond = end - start;
		frameCount++; 
		//SDL_Delay(10);

	}//end maingameplay whileloop
	
	
	// free entire world
	for(GameBaseList::iterator iter = World.begin() ; iter != World.end() ; iter++)
	{
		delete *iter;
		*iter = 0;
	}

	SDL_Quit();
	return 0;   
    
}
